﻿//Another question going with this filter is, if its really useful!?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

//TODO: check if weighting makes sense
namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Maybe this filter will die soon.
    /// </summary>
    public class Weighting : BaseImageFilter
    {
        protected int m_nFactor = 15;
        protected int m_nOffset = 15;
        protected bool m_bClip = true;

        /// <summary>
        /// 
        /// </summary>
        public Weighting()
            : this(1,0)
        {
        }

        /// <summary>
        /// primary constructor specifying factor and offset
        /// </summary>
        /// <param name="_nFactor"></param>
        /// <param name="_nOffset"></param>
        public Weighting(int _nFactor, int _nOffset)
        {
            m_nFactor = _nFactor;
            m_nOffset = _nOffset;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_weighting"></param>
        internal Weighting(Weighting _weighting)
        {
            this.m_nFactor = _weighting.m_nFactor;
            this.m_nOffset = _weighting.m_nOffset;
        }

        /// <summary>
        /// Gets or sets factor
        /// </summary>
        public int Factor
        {
            get { return m_nFactor; }
            set { m_nFactor = value; }
        }

        //TODO: check if this can be deleted (inheritance)
        /// <summary>
        /// Gets or sets offset
        /// </summary>
        public int Offset
        {
            get { return m_nOffset;}
            set { m_nOffset = value; }
        }

        /// <summary>
        /// gets or sets clip
        /// </summary>
        public bool Clip
        {
            get { return m_bClip; }
            set { m_bClip = value; }
        }

        /// <summary>
        /// executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;
            List<Point> aCoord = Definitions.EnvironmentPointList;
            int nKoordCount = aCoord.Count;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            int y = 0;
            int x = 0;

            Color color = Color.Transparent;

            for (y = 1; y < nHeight - 1; y++)
            {
                for (x = 1; x < nWidth - 1; x++)
                {
                    color = bitmap.GetPixel(x, y);

                    int nColor = 0;
                    List<Color> aColor = new List<Color>();
                    foreach (Point point in aCoord)
                    {
                        aColor.Add(bitmap.GetPixel(x + point.X, y + point.Y));
                    }
                    color = GetColorValue(aColor);
                    bitmap.SetPixel(x, y, color);
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// Gets the color value.
        /// </summary>
        /// <param name="_aColor">Color of the _a.</param>
        /// <returns></returns>
        private Color GetColorValue(List<Color> _aColor)
        {
            double dValue = 1;
            double dR = 0;
            double dG = 0;
            double dB = 0;
            foreach(Color color in _aColor)
            {
                if (color.R != 0) dR += 1.0f / color.R;
                if (color.G != 0) dG += 1.0f / color.G;
                if (color.B != 0) dB += 1.0f / color.B;
            }

            double dCount = (double)_aColor.Count;
            if (dR != 0.0f) dR = dCount / dR;
            if (dG != 0.0f) dG = dCount / dG;
            if (dB != 0.0f) dB = dCount / dB;

            int nR = (int)dR * m_nFactor + m_nOffset;
            int nG = (int)dG * m_nFactor + m_nOffset;
            int nB = (int)dB * m_nFactor + m_nOffset;

            if (m_bClip)
            {
                if (nR < 0) nR = 0;
                if (nG < 0) nG = 0;
                if (nB < 0) nB = 0;
                if (nR > 255) nR = 255;
                if (nG > 255) nG = 255;
                if (nB > 255) nB = 255;
            }
            else
            {
                nR %= 255;
                nG %= 255;
                nB %= 255;
            }
            return Color.FromArgb(nR, nG, nB);
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new Weighting(this);
        }
    }
}
